#ifndef CAP_CAP_DESC_H
#define CAP_CAP_DESC_H

#include <utils/types.h>
#include <seminix/bug.h>
#include <libseminix/types.h>

#define CAPDESC_INDEX_BITS  ((sizeof(int)*8) - CAPDESC_CNODE_BITS)
__static_assert(CAPDESC_INDEX_BITS == 16, "cap desc: No space for cnode bits field in cap desc");

#define CAPDESC_CNODE_SHIFT     0
#define CAPDESC_CNODE_MASK      BIT_GENMASK(CAPDESC_CNODE_BITS)
#define CAPDESC_CNODE_MAX       BIT(CAPDESC_CNODE_BITS)

#define CAPDESC_INDEX_SHIFT     CAPDESC_CNODE_BITS
#define CAPDESC_INDEX_MASK      BIT_GENMASK(CAPDESC_INDEX_BITS)
#define CAPDESC_INDEX_MAX       BIT(CAPDESC_INDEX_BITS)

static inline int capdesc_set_desc(int cnode, int index)
{
    if (cnode == THIS_CNODE_CAPDESC)
        cnode = 0;
    else
        BUG_ON(!(cnode & CAPDESC_CNODE_MASK));
    BUG_ON(!(index & CAPDESC_INDEX_MASK));

    return (cnode << CAPDESC_CNODE_SHIFT) | (index << CAPDESC_INDEX_SHIFT);
}

static inline int capdesc_get_cnode(int cd)
{
    return (cd >> CAPDESC_CNODE_SHIFT) & CAPDESC_CNODE_MASK;
}

static inline int capdesc_get_index(int cd)
{
    return (cd >> CAPDESC_INDEX_SHIFT) & CAPDESC_INDEX_MASK;
}

static inline bool capdesc_has_cnode(int cd)
{
    return !!(capdesc_get_cnode(cd) != 0);
}

#endif /* !CAP_CAP_DESC_H */
